package org.smr.ministore.entities;

import org.apache.commons.collections.CollectionUtils;
import org.blade.entities.base.BizEntity;
import org.smr.ministore.entities.vo.Assign2OrganVO;
import org.smr.ministore.entities.vo.Assign2OrgansVO;
import org.smr.ministore.entities.vo.GoodsVO;
import org.smr.ministore.entities.vo.OrganVO;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public abstract class Assign2Organ<T extends BizEntity<Long>> extends BizEntity<Long>{


    /**
     * 商品指派
     *
     * @return GoodsOrgan 组织商品
     */
    public T assignTo(OrganVO assignee) {
        T assignOrgan = this.initReference();
        this.attachValue(assignOrgan);
        assignOrgan.setOrganId(assignee.getId());
        assignOrgan.setOrganPath(assignee.getOrganPath());
        assignOrgan.setTenantId(assignee.getTenantId());
        assignOrgan.setCreateBy(this.getCreateBy());
        assignOrgan.setUpdateBy(this.getUpdateBy());
        return assignOrgan;
    }

    /**
     * 附加组织编号
     *
     * @param organ
     */
    public abstract void attachValue(T organ);

    public abstract T initReference();


    /**
     * 批量商品指派给组织
     *
     * @param assign2Organ Assign2OrganVO 商品集合
     * @return List<GoodsOrgan>
     */
    public List<T> assignTo(Assign2OrganVO assign2Organ) {
        List<GoodsVO> goodsList = assign2Organ.getGoodsList();
        List<T> refereces = new ArrayList<>();
        goodsList.forEach(goodsVO -> {
            T referece = this.initReference();
            this.attachValue(referece);
            referece.setUpdateBy(assign2Organ.getUpdateBy());
            referece.setCreateBy(assign2Organ.getCreateBy());
            referece.setOrganId(assign2Organ.getId());
            refereces.add(referece);
        });
        return refereces;
    }



    /**
     * 商品指派批量组织
     *
     * @param assigneeOrgans
     * @return List<GoodsOrgan>
     */
    public List<T> assignTo(Assign2OrgansVO assigneeOrgans) {
        this.setId(assigneeOrgans.getId());
        List<OrganVO> assignees = assigneeOrgans.getAssignees().parallelStream().map(organVO -> {
            organVO.setTenantId(assigneeOrgans.getTenantId());
            return organVO;
        }).collect(Collectors.toList());
        List<T> assignOrgans = assignees.stream().map(this::assignTo).collect(Collectors.toList());
        return assignOrgans;
    }


    /**
     * 根据持久化的关联得出需要指派的组织
     *
     * @param referencesPersistence 持久化的关联
     * @param assignee               被指派的组织
     * @return Assign2OrgansVO
     */
    public Assign2OrgansVO want2Assign(List<T> referencesPersistence, Assign2OrgansVO assignee) {
        if (CollectionUtils.isEmpty(assignee.getAssignees())) {
            return assignee;
        }
        Set<Long> organIds  = referencesPersistence.parallelStream().map(T::getOrganId).collect(Collectors.toSet());
        List<OrganVO> want2Assign = assignee.getAssignees().stream().filter(go -> {
            return !organIds.contains(go.getId());
        }).collect(Collectors.toList());
        assignee.setAssignees(want2Assign);
        return assignee;
    }


}
